from multiprocessing import Queue

import PySide6
import numpy as np
from PySide6 import QtCore
from PySide6.QtCore import Qt, Signal, QPoint, QSize, QEvent
from PySide6.QtGui import QValidator, QCursor, QColor, QResizeEvent
from PySide6.QtWidgets import QPushButton, QLabel, QGridLayout, QComboBox, QListWidgetItem, QCheckBox, QLineEdit, \
    QListWidget, QFrame, QSizePolicy, QWidget
import pyqtgraph as pg
from pyqtgraph import PlotWidget

from main_ui.dock_console import Dock_Console, DraggableWidget, CustomTabWidget, My_ScrollArea

first_resize_flag = 0  # 全局变量，记录是否为第一次打开程序


class Dock_Scope(Dock_Console):
    def __init__(self,
                 parent,
                 config=None,
                 title_bar_widgets=None,
                 signal_online_stateChanged=Signal(),
                 grid_size=None):
        # 存储实例的列表, 因调用顺序问题先放在这里
        super(Dock_Scope, self).__init__(parent, config, title_bar_widgets, signal_online_stateChanged)

        # 覆盖数据内容
        if grid_size is None:
            self.grid_size = [50, 50]
        else:
            self.grid_size = grid_size
        if title_bar_widgets is None:
            title_bar_widgets = []
        parent.addDockWidget(Qt.RightDockWidgetArea, self)
        self.setWindowTitle('示波器')
        self.setTitleBarWidget(title_bar_widgets)
        self.DraggableWidget_Object = Scope_Widget

        # 由于循环导入，所以这里是从Channel_Manage中复制过来的
        self.interval_pack_dict = {'100us': 1,
                                   '200us': 2,
                                   '400us': 4,
                                   '500us': 5,
                                   '1ms': 10,
                                   '2ms': 20,
                                   '2.5ms': 25,
                                   '5ms': 50,
                                   '10ms': 100
                                   }

        # 创建刷新用的定时器
        self.timer_refresh_plot_widget = QtCore.QTimer()
        self.timer_refresh_plot_widget.timeout.connect(self.func_timer_refresh_ploat_widget)
        self.timer_refresh_plot_widget.start(100)

        # 创建变量
        self.name_list = None
        self.channel_num = 0  # 通道个数的变量
        self.interval_pack = 1  # 每包的间隔

        self.tabWidget = Scope_TabWidget(self.scroll_area,
                                         grid_size=self.grid_size,
                                         config=self.config,
                                         signal_table_info=self.signal_table_info,
                                         signal_online_stateChanged=self.signal_online_stateChanged,
                                         timer_scrollLabel=self.timer_scrollLabel,
                                         table_info=self.table_info,
                                         queue_logging=self.queue_logging,
                                         name_lsit=self.name_list,
                                         signal_operat=self.signal_operat)
        self.scroll_area.setWidget(self.tabWidget)
        self.load_config()

        # 判断是否为空的控制台
        if self.tabWidget.draggable_widgets == {'New Tab': {}}:
            self.close()
        else:
            pass

    def add_draggableWidget(self, config=None):
        self.tabWidget.add_draggableWidget(config=config)

    def setSize(self):
        """ 重新设置size , 用来刷新界面，用来应对删除控件后的残留问题"""
        self.resize(QSize(self.size().width() + 1, self.size().height() + 1))
        self.resize(QSize(self.size().width() - 1, self.size().height() - 1))

    def update_channel(self, config, interval_of_pack, channel_num_flag):
        """ 更新 通道数据 """
        if channel_num_flag:
            self.channel_num = int(config['channel_num'])
            self.interval_pack = interval_of_pack
            show_text = list(self.interval_pack_dict.keys())[
                list(self.interval_pack_dict.values()).index(self.interval_pack)]
            self.titleBarWidget().title.setFixedWidth(80)
            self.titleBarWidget().title.setText('示波器(' + show_text + ')')
            # self.setWindowTitle('示波器(' + str(self.interval_pack) + ')')
        if config:
            self.name_list = config['channel_name'][:self.channel_num]
            # for widget in self.draggable_widgets.values():
            #     widget.update_channel(self.name_list, self.interval_pack)
            #     widget.plot_refresh()
            self.tabWidget.update_channel(self.name_list, self.interval_pack)
            try:
                self.timer_refresh_plot_widget.stop()
                self.timer_refresh_plot_widget.start(int(config['scope_refresh_frequency']))
            except Exception as e:
                pass

    def update_buf(self, time, data, index):
        """ 更新共享内存 """
        self.tabWidget.update_buf(time, data, index)
        # for widget in self.draggable_widgets.values():
        #     widget.update_buf(time, data, index)

    def plot_refresh(self):
        """ 刷新所有视图的控件 """
        self.tabWidget.plot_refresh()
        # for widget in self.draggable_widgets.values():
        #     widget.plot_refresh()

    def func_timer_refresh_ploat_widget(self):
        """ 关联定时器函数为plot界面刷新数据 """
        self.tabWidget.func_timer_refresh_ploat_widget()
        # for widget in self.draggable_widgets.values():
        #     widget.func_timer_refresh_ploat_widget()

    # def delete_one_widget(self, widget):
    #     """删除指定控件"""
    #     str = ''
    #     for key, value in self.draggable_widgets.items():
    #         if value == widget:
    #             str = key
    #     del self.draggable_widgets[str]
    #     widget.delete_myself()
        # self.setSize()

    def resizeEvent(self, event: QResizeEvent) -> None:
        global first_resize_flag  # 声明全局变量
        # 获取当前 DockWidget 的大小
        dockSize = event.size()

        # 获取当前鼠标的全局位置
        mousePos = QCursor.pos()

        # 将全局位置转换为 DockWidget 的相对位置
        relativeMousePos = self.mapFromGlobal(mousePos)

        # 判断鼠标是否在左边框上
        if relativeMousePos.x() <= 5 and relativeMousePos.x() > -5:
            first_resize_flag = 1

        # 调用父类的 resizeEvent 方法，保持默认操作
        super().resizeEvent(event)

    def load_config(self):
        global first_resize_flag  # 声明全局变量
        if self.config is not None:
            try:
                # pass
                if first_resize_flag == 0:
                    self.scroll_area.setSize(self.config['size'])
                else:
                    self.set_size(self.config['size'])
                # first_resize_flag += 1
                # self.scroll_area.setSize(self.config['size'])
                # self.set_size(self.config['size'])
            except Exception as e:
                print(1, e)

            # for widget_config in self.config['widgets']:
            #     # try:
            #     self.add_draggableWidget(config=widget_config)
                # except Exception as e:
                #     print(2, e)
        self.tabWidget.load_config()


class Scope_TabWidget(CustomTabWidget):
    def __init__(self,
                 parent=None,
                 grid_size=None,
                 config=None,
                 signal_table_info=Signal(),
                 delete_self_signal=Signal(),
                 signal_online_stateChanged=Signal(),
                 timer_scrollLabel=Signal(),
                 queue_logging=Queue(),
                 table_info=None,
                 name_lsit=None,
                 signal_operat=Signal()
                 ):
        super(Scope_TabWidget, self).__init__(parent=parent,
                                              grid_size=grid_size,
                                              config=config,
                                              signal_table_info=signal_table_info,
                                              signal_online_stateChanged=signal_online_stateChanged,
                                              timer_scrollLabel=timer_scrollLabel,
                                              table_info=table_info,
                                              queue_logging=queue_logging,)
        if grid_size is None:
            self.grid_size = [50, 50]
        else:
            self.grid_size = grid_size
        self.name_list = name_lsit
        self.signal_operat = signal_operat
        self.DraggableWidget_Object = Scope_Widget
        # self.add_tab('New Tab')

        # 初始化变量
        self.scope_time = None
        self.scope_data = None
        self.scope_index = None

    def add_draggableWidget(self, config=None, parent_name=None):
        if not self.drag_enable:
            return
        if parent_name is None:
            parent_name = self.tabText(self.currentIndex())
        if config is None:
            # 生成config信息
            config = {
                'sampling_interval': '1',
                'sampling_count': '500',
                'select_index': []
            }
        else:
            pass

        # 获取名为parent_name的widget
        for i in range(self.count()):
            if self.tabText(i) == parent_name:
                widget = self.widget(i).widget
                break

        # 添加组件
        widget = Scope_Widget(parent=widget,
                              grid_size=self.grid_size,
                              name_list=self.name_list,
                              delete_self_signal=self.delete_self_signal,
                              signal_online_stateChanged=self.signal_online_stateChanged,
                              config=config,
                              signal_operat=self.signal_operat)

        # 将添加的dock_widget记录下来方便访问
        if self.draggable_widgets[parent_name] == {}:
            self.draggable_widgets[parent_name]['0'] = widget
        else:
            self.draggable_widgets[parent_name][str(int(list(self.draggable_widgets[parent_name].keys())[-1]) + 1)] = widget

        # 刷新buf
        widget.update_buf(self.scope_time, self.scope_data, self.scope_index)

        # 刷新画布大小
        # self.resize(QSize(self.size().width() + 1, self.size().height() + 1))

        # if len(self.draggable_widgets) == 1 and not self.isVisible():
        #     self.show()
        #     self.signal_operat.emit(6, 1, [type(self)])

    def delete_one_widget(self, widget):
        """删除指定控件"""
        str = ''
        for key, value in self.draggable_widgets[self.tabText(self.currentIndex())].items():
            if value == widget:
                str = key
        del self.draggable_widgets[self.tabText(self.currentIndex())][str]
        widget.delete_myself()

    def update_channel(self, name_list=None, interval_pack=1):
        for i in range(self.count()):
            for widget in self.draggable_widgets[self.tabText(i)].values():
                widget.update_channel(name_list, interval_pack)
                widget.plot_refresh()

    def update_buf(self, time, data, index):
        self.scope_time = time
        self.scope_data = data
        self.scope_index = index
        """ 更新共享内存 """
        for i in range(self.count()):
            for widget in self.draggable_widgets[self.tabText(i)].values():
                widget.update_buf(time, data, index)

    def plot_refresh(self):
        """ 刷新所有视图的控件 """
        for i in range(self.count()):
            for widget in self.draggable_widgets[self.tabText(i)].values():
                widget.plot_refresh()

    def func_timer_refresh_ploat_widget(self):
        """ 关联定时器函数为plot界面刷新数据 """
        for widget in self.draggable_widgets[self.tabText(self.currentIndex())].values():
            widget.func_timer_refresh_ploat_widget()


class Scope_Widget(DraggableWidget):
    """ 可拖拽的自定义波形视图控件 继承于DraggableWidget """
    max_sampling_interval = 100                 # 最大显示间隔
    max_sampling_count = 2000                   # 最大显示数量
    max_channel_count = 100                     # 通道的最多数量
    custom_mem_size = max_sampling_count * (max_sampling_interval + 1)    # 留一些余地，避免重复数据影响波形
    interval_pack = 1

    def __init__(self,
                 parent=None,
                 grid_size=None,
                 name_list=None,
                 config=None,
                 signal_operat=Signal(),
                 delete_self_signal=Signal(),
                 signal_online_stateChanged=Signal(),):
        super(Scope_Widget, self).__init__(parent=parent,
                                           grid_size=grid_size,
                                           delete_self_signal=delete_self_signal,
                                           config=config,
                                           signal_online_stateChanged=signal_online_stateChanged)

        if grid_size is None:
            self.grid_size = [50, 50]
        else:
            self.grid_size = grid_size

        self.setMinimumWidth(self.grid_size[0] * 8)
        self.setMinimumHeight(self.grid_size[1] * 6)

        self.name_list = name_list
        # self.color = ['r', 'g', 'y', 'c', 'm', 'k', 'b']
        self.color = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f"]

        # 通过config处理相应参数
        count = self.config['sampling_count']  # 避免因间隔改变修改config导致个数为空
        self.edit_sampling_interval.setText(self.config['sampling_interval'])
        self.edit_sampling_count.setText(count)

        # 创建变量
        self.sampling_time = 0.0001                             # 底层的间隔时间
        self.interval_pack = 1                                  # 默认的间隔
        self.show_index = 0                                     # 用于显示现在该刷新到哪了
        self.curve = []  # 存储画布实例
        self.list_index = []  # 存储选择的索引
        self.scope_data = []  # 存储刷新的数据
        self.mouse_pos = None  # 存储鼠标的pos
        # 传输数据的共享内存
        self.scope_time_shm = None
        self.scope_data_shm = None
        self.scope_index_shm = None

        # 放大缩小的变量
        self.setMouseTracking(True)  # 设置widget鼠标跟踪
        self.padding = 3  # 设置边界宽度为3
        self.corner_drag = False
        self.bottom_drag = False
        self.right_drag = False
        self.right_rect = []
        self.bottom_rect = []
        self.corner_rect = []
        self.resize_flag = True

        if 'size' not in self.config.keys():
            self.resize(QSize(self.grid_size[0] * 8, self.grid_size[1] * 6))
            self.config['size'] = [8, 6]
        else:
            self.resize(QSize(self.config['size'][0] * self.grid_size[0], self.config['size'][1] * self.grid_size[1]))
            # self.resize(QSize(self.config['size'][0], self.config['size'][1]))
            # self.config['size'] = [int(self.config['size'][0] / self.grid_size[0]), int(self.config['size'][1] / self.grid_size[1])]

        # if 'sampling_interval' in self.config.keys():
        #     self.edit_sampling_interval.setText(self.config['sampling_interval'])
        # if 'sampling_count' in self.config.keys():
        #     print(111111)
        #     self.edit_sampling_count.setText(self.config['sampling_count'])

        # 如果有name_list就追加数据
        if self.name_list:
            self.combox.set_items(self.name_list)
        else:
            pass

    def init_widget(self):
        """名称+自定义控件初始化"""
        # 创建横向10 纵向10的布局
        self.layout = QGridLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)

        # 创建采样间隔
        self.label_sampling_interval = QLabel('间隔:')
        self.edit_sampling_interval = QLineEdit()
        self.edit_sampling_interval.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)  # 禁用右键菜单
        intValidator = AgeValidator(self.max_sampling_interval)
        self.edit_sampling_interval.setValidator(intValidator)
        # self.edit_sampling_interval.setFixedWidth(40)
        self.edit_sampling_interval.setSizePolicy(QSizePolicy.Policy.Expanding,
                                                  QSizePolicy.Policy.Fixed)
        self.edit_sampling_interval.textChanged.connect(self.show_time)
        self.layout.addWidget(self.label_sampling_interval, 0, 0, 1, 1,
                              Qt.AlignCenter)
        self.layout.addWidget(self.edit_sampling_interval, 0, 1, 1, 1,
                              Qt.AlignCenter)

        # 创建采样个数
        self.label_sampling_count = QLabel('个数:')
        self.edit_sampling_count = QLineEdit()
        self.edit_sampling_count.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)
        intValidator = AgeValidator(self.max_sampling_count)
        self.edit_sampling_count.setValidator(intValidator)
        self.edit_sampling_count.setSizePolicy(QSizePolicy.Policy.Expanding,
                                               QSizePolicy.Policy.Fixed)
        self.edit_sampling_count.textChanged.connect(self.show_time)
        self.layout.addWidget(self.label_sampling_count, 0, 2, 1, 1,
                              Qt.AlignCenter)
        self.layout.addWidget(self.edit_sampling_count, 0, 3, 1, 1,
                              Qt.AlignCenter)

        # 创建采样时间
        self.label_show_time = QLabel('时长: ')
        self.label_show_time.setAlignment(Qt.AlignCenter)
        # self.label_show_time.setFixedWidth(80)
        self.label_show_time.setSizePolicy(QSizePolicy.Policy.Expanding,
                                           QSizePolicy.Policy.Fixed)
        self.layout.addWidget(self.label_show_time, 0, 4, 1, 2, Qt.AlignCenter)

        # 创建下拉列表和清除按钮
        self.combox = My_ComBox()
        self.combox.setFixedWidth(80)
        self.combox.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)
        self.combox.check_changed.connect(self.plot_refresh)
        self.combox.setSizePolicy(QSizePolicy.Policy.Expanding,
                                  QSizePolicy.Policy.Fixed)
        self.layout.addWidget(self.combox, 0, 6, 1, 3, Qt.AlignCenter)

        # 创建暂停按钮
        self.button_pause = QPushButton('暂停')
        self.button_pause.setCheckable(True)
        self.button_pause.clicked.connect(self.func_button_pause)
        self.button_pause.setSizePolicy(QSizePolicy.Policy.Expanding,
                                        QSizePolicy.Policy.Fixed)
        self.layout.addWidget(self.button_pause, 0, 9, 1, 2, Qt.AlignCenter)

        # 创建视图区
        pg.setConfigOption('background', 'w')  # 白色背景
        pg.setConfigOption('foreground', 'k')
        pg.setConfigOption('antialias', True)
        # pg.setConfigOptions(leftButtonPan=False, antialias=False, foreground=QColor(0, 0, 0))  # 禁止拉动图表，抗锯齿,坐标轴颜色

        self.plot_widget = My_Plot_Widget(self)
        # self.legend = pg.LegendItem((80, 60), offset=(70, 20))
        self.plot_widget.addLegend()
        self.plot_widget.showGrid(x=True, y=True)
        # self.plot_widget.setLabel('left', 'Value', units='V')
        self.plot_widget.setLabel('bottom', 'Time', units='s')
        # self.plot_widget.setMenuEnabled(False)
        self.plot_widget.setMouseEnabled(x=False, y=False)  # 禁用轴操作
        self.layout.addWidget(self.plot_widget, 1, 0, 19, 11)

        """ 设置背景颜色 """
        # 默认颜色
        self.default_StyleSheet = """
        """

        # 创建选中的样式
        self.select_StyleSheet = """
            QFrame{
                background-color: lightblue;
            }
        """
        self.setStyleSheet(self.default_StyleSheet)

    # 关联时间显示
    def show_time(self):
        """ 通过间隔和个数计算显示在页面上的时间 """
        if self.edit_sampling_interval.text():
            if self.edit_sampling_interval.text().isdigit():
                interval = int(self.edit_sampling_interval.text())
                if interval > self.max_sampling_interval:
                    interval = self.max_sampling_interval
                    self.edit_sampling_interval.setText('100')
                elif interval == 0:
                    interval = 1
            else:
                interval = 1
        else:
            interval = 1
        if self.edit_sampling_count.text():
            count = int(self.edit_sampling_count.text())
            if count == 0:
                count = 1
        else:
            count = 1
        echo_time = interval * count * 100 * self.interval_pack
        if echo_time >= 1000000:
            echo_time2 = echo_time / 1000000
            if echo_time2.is_integer():
                time_str = str(int(echo_time2)) + 's'
            else:
                time_str = str(echo_time2) + 's'
        elif echo_time >= 1000:
            echo_time2 = echo_time / 1000
            if echo_time2.is_integer():
                time_str = str(int(echo_time2)) + 'ms'
            else:
                time_str = str(echo_time2) + 'ms'
        else:
            time_str = str(echo_time) + 'us'
        self.label_show_time.setText('时长:' + time_str)

        self.config['sampling_interval'] = self.edit_sampling_interval.text()
        self.config['sampling_count'] = self.edit_sampling_count.text()

    def plot_refresh(self):
        """ 更新画布和选择 """
        try:
            self.curve = []
            self.list_index = []
            self.scope_data = []
            self.plot_widget.clear()
            self.plot_widget.clearPlots()
            for i, item in enumerate(self.combox.Selectlist()):
                curve = self.plot_widget.plot(pen=self.color[i], name=item)
                # self.legend.addItem(curve, item)
                self.curve.append(curve)
                self.list_index.append(self.combox.Selectindex()[i])
            self.config['select_index'] = self.list_index
            self.show_index = 0
        except:
            pass

    def func_timer_refresh_ploat_widget(self):
        """ 父类引发的定时器，用来刷新plot_widget """
        if self.scope_index_shm:
            if self.button_pause.isChecked():
                pass
            else:
                # 处理个数
                if self.edit_sampling_count.text():
                    if self.edit_sampling_count.text().isdigit():
                        count = int(self.edit_sampling_count.text())
                        if count == 0:
                            count = 1
                        elif count > self.max_sampling_count:
                            count = self.max_sampling_count
                            self.edit_sampling_count.setText('2000')
                    else:
                        count = 500
                        self.edit_sampling_count.setText('500')

                else:
                    count = 1
                # 处理间隔
                if self.edit_sampling_interval.text():
                    if self.edit_sampling_interval.text().isdigit():
                        interval = int(self.edit_sampling_interval.text())
                        if interval > self.max_sampling_interval:
                            interval = self.max_sampling_interval
                            self.edit_sampling_interval.setText('100')
                        elif interval == 0:
                            interval = 1
                    else:
                        interval = 1
                        self.edit_sampling_interval.setText('1')
                else:
                    interval = 1

                # 获取与上一次的差值
                while self.calculate_distance(self.scope_index_shm[0], self.show_index) >= interval:
                    self.show_index += interval
                    if self.show_index >= self.max_sampling_count * (self.max_sampling_interval + 10):
                        self.show_index -= self.max_sampling_count * (self.max_sampling_interval + 10)
                # else:
                #     return

                # 获取要显示的序列  -100 是为了不让最后一包正在更新的显示出来
                index = (self.show_index - int(100 / self.interval_pack) - np.arange(0, count * interval, interval)) % (
                            self.custom_mem_size)
                for i in range(len(self.curve)):
                    self.curve[i].setData(x=self.scope_time_shm[index, 0] * self.sampling_time,
                                          y=self.scope_data_shm[index, self.list_index[i]])
                # 设置x轴范围， 目的是让图形两边没有留白
                self.plot_widget.setXRange(min(self.scope_time_shm[index, 0] * self.sampling_time),
                                           max(self.scope_time_shm[index, 0] * self.sampling_time),
                                           padding=0)

        else:
            pass

    def calculate_distance(self, num1, num2):
        distance = num1 - num2
        if distance >= 0:
            return distance
        else:
            return distance + self.custom_mem_size

    def update_channel(self, name_list=None, interval_pack=1):
        """ 更新所有的combox序列 """
        if name_list:
            # 如果通道列表变了就刷新图例
            if name_list == self.name_list:
                self.scope_data = []
                pass
            else:
                self.name_list = name_list
                self.combox.set_items(name_list)
                self.combox.select_items(self.config['select_index'])
                self.combox.show()
        if interval_pack:
            self.interval_pack = interval_pack
            self.sampling_time = 0.0001 * interval_pack

        self.show_time()

    def update_buf(self, time, data, index):
        """ 更新共享内存 """
        self.scope_time_shm = time
        self.scope_data_shm = data
        self.scope_index_shm = index

    def func_button_pause(self):
        if not self.button_pause.isChecked():
            # self.plot_widget.set_mouse_enable(False)
            self.plot_widget.setMouseEnabled(x=False, y=False)  # 禁用轴操作
            self.button_pause.setText('暂停')
            self.plot_widget.enableAutoRange()
        else:
            # self.plot_widget.set_mouse_enable(True)
            self.plot_widget.setMouseEnabled(x=True, y=True)  # 打开轴操作
            self.button_pause.setText('继续')
        self.plot_widget.set_mouse_enable(self.button_pause.isChecked())

    def right_click(self):
        """ 重载父类的右键删除方法，用来屏蔽在视图上的右键事件 """
        if self.mouse_pos:
            # 左上边界的x值
            boundary_LT_x = self.plot_widget.pos().x()
            boundary_LT_y = self.plot_widget.pos().y()
            boundary_RT_x = boundary_LT_x + self.plot_widget.width()
            boundary_RB_Y = boundary_LT_y + self.plot_widget.height()
            if boundary_LT_x < self.mouse_pos.x() < boundary_RT_x and boundary_LT_y < self.mouse_pos.y() < boundary_RB_Y:
                pass
            else:
                super().right_click()
            self.mouse_pos = None
        else:
            pass

    def event(self, event):
        if event.type() == QEvent.Wheel:
            return False
        return super().event(event)

    # def right_click_delete(self):
    #     self.layout.removeWidget(self.plot_widget)
    #     self.plot_widget.deleteLater()
    #     super().right_click_delete()
    #     self.signal.emit(22, [None], [None])

    def set_drag_enable(self, flag):
        self.resize_flag = not flag
        super(Scope_Widget, self).set_drag_enable(flag)

    def mousePressEvent(self, event):
        if not self.resize_flag:
            return
        """ 重载父类的鼠标事件， 如果触发放大缩小事件就处理， 如果没有就返回给父类处理拖动事件"""
        if (event.button() == Qt.LeftButton) and (event.pos() in self.corner_rect):
            # 鼠标左键点击右下角边界区域
            self.corner_drag = True
            self.original_size = self.size()
            event.accept()
        elif (event.button() == Qt.LeftButton) and (event.pos() in self.right_rect):
            # 鼠标左键点击右侧边界区域
            self.right_drag = True
            self.original_size = self.size()
            event.accept()
        elif (event.button() == Qt.LeftButton) and (event.pos() in self.bottom_rect):
            # 鼠标左键点击下侧边界区域
            self.bottom_drag = True
            self.original_size = self.size()
            event.accept()
        else:
            self.mouse_pos = event.pos()
            super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        """ 继承父类的鼠标移动事件 """
        if not self.resize_flag:
            return
        if event.pos() in self.corner_rect:
            self.setCursor(Qt.SizeFDiagCursor)
        elif event.pos() in self.bottom_rect:
            self.setCursor(Qt.SizeVerCursor)
        elif event.pos() in self.right_rect:
            self.setCursor(Qt.SizeHorCursor)
        else:
            self.setCursor(Qt.ArrowCursor)
        # 当鼠标左键点击不放及满足点击区域的要求后，分别实现不同的窗口调整
        if Qt.LeftButton and self.right_drag:
            # 右侧调整窗口宽度
            self.resize(event.pos().x(), self.height())
            event.accept()
        elif Qt.LeftButton and self.bottom_drag:
            # 下侧调整窗口高度
            self.resize(self.width(), event.pos().y())
            event.accept()
        elif Qt.LeftButton and self.corner_drag:
            # 右下角同时调整高度和宽度
            self.resize(event.pos().x(), event.pos().y())
            event.accept()
        if self.corner_drag == True or self.right_drag == True or self.bottom_drag == True:
            pass
        else:
            super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        """ 继承父类的鼠标松开事件 """
        if not self.resize_flag:
            return
        # 判断是否跟网格对齐
        if self.corner_drag == True or self.right_drag == True or self.bottom_drag == True:
            if self.size().width() % self.grid_size[0] != 0:
                width = int(self.size().width() / self.grid_size[0]) * self.grid_size[0]
            else:
                width = self.size().width()
            if self.size().height() % self.grid_size[1] != 0:
                height = int(self.size().height() / self.grid_size[1]) * self.grid_size[1]
            else:
                height = self.size().height()
            self.resize(QSize(width, height))
            # 判断是否重合
            try_count = 10
            while self.IsIntersects(self.pos().x(), self.pos().y()) and try_count > 0:  # 重合就等比例缩小
                try_count -= 1
                self.resize(QSize(self.size().width() - self.grid_size[0], self.size().height() - self.grid_size[1]))
            self.corner_drag = False
            self.bottom_drag = False
            self.right_drag = False
        else:
            super().mouseReleaseEvent(event)

    def resizeEvent(self, event: PySide6.QtGui.QResizeEvent) -> None:
        # 重新调整边界范围以备实现鼠标拖放缩放窗口大小，采用三个列表生成式生成三个列表
        if self.resize_flag:
            self.right_rect = [QPoint(x, y) for x in range(self.width() - self.padding, self.width() + 1)
                               for y in range(1, self.height() - self.padding)]
            self.bottom_rect = [QPoint(x, y) for x in range(1, self.width() - self.padding)
                                for y in range(self.height() - self.padding, self.height() + 1)]
            self.corner_rect = [QPoint(x, y) for x in range(self.width() - self.padding, self.width() + 1)
                                for y in range(self.height() - self.padding, self.height() + 1)]
            # 记录size
            # self.config['size'] = [self.size().width(), self.size().height()]
            self.config['size'] = [int(self.size().width() / self.grid_size[0]),
                                   int(self.size().height() / self.grid_size[1])]


# 自定义combox类
class My_ComBox(QComboBox):
    check_changed = Signal(int)

    def __init__(self, items=[]):  # items==[str,str...]
        super(My_ComBox, self).__init__()
        self.items = items
        self.button_cancel = QPushButton('取消选择')
        self.button_cancel.setFixedHeight(20)
        self.button_cancel.clicked.connect(self.cancel_select)
        self.select_index_list = []
        self.loadItems()

    def loadItems(self):
        self.qCheckBox = []
        self.qLineEdit = QLineEdit()
        qListWidget = QListWidget()
        qListWidget.setFixedWidth(self.width()*2)
        self.row_num = len(self.items)
        qitem = QListWidgetItem(qListWidget)
        qListWidget.setItemWidget(qitem, self.button_cancel)
        for i in range(self.row_num):
            self.qCheckBox.append(QCheckBox())
            self.qCheckBox[i].setText(self.items[i])
            self.qCheckBox[i].setToolTip('通道' + str(i) + ':' + self.items[i])
            if self.items[i][0:2] == '通道':
                pass
            else:
                qItem = QListWidgetItem(qListWidget)
                qListWidget.setItemWidget(qItem, self.qCheckBox[i])
            self.qCheckBox[i].stateChanged.connect(self.show)

        self.setLineEdit(self.qLineEdit)
        self.setModel(qListWidget.model())
        self.setView(qListWidget)
        self.qLineEdit.setReadOnly(False)
        self.qLineEdit.setText('通道选择')
        self.qLineEdit.setReadOnly(True)

    def hidePopup(self):
        if self.Selectindex() == self.select_index_list:
            pass
        else:
            self.select_index_list = self.Selectindex()
            self.check_changed.emit(0)
        # self.button_cancel.setText('取消全部选择')
        # self.button_cancel.setEnabled(False)
        return QComboBox.hidePopup(self)

    def showPopup(self):
        # 重写showPopup方法，避免下拉框数据多而导致显示不全的问题
        select_list = self.Selectlist()  # 当前选择数据
        self.loadItems()  # 重新添加组件
        for select in select_list:
            index = self.items[:].index(select)
            self.qCheckBox[index].setChecked(True)  # 选中组件
        # self.button_cancel.setText('取消全部选择')
        return QComboBox.showPopup(self)

    def Selectlist(self):
        Outputlist = []
        for i in range(self.row_num):
            if self.qCheckBox[i].isChecked() == True:
                Outputlist.append(self.qCheckBox[i].text())
        return Outputlist

    def Selectindex(self):
        Outoutindex = []
        try:
            for i in range(self.row_num):
                if self.qCheckBox[i].isChecked() == True:
                    Outoutindex.append(i)
        except:
            pass
        return Outoutindex

    def select_items(self, items):
        if items:
            for i in range(len(items)):
                try:
                    if self.qCheckBox[int(items[i])].text()[0:2] == '通道':
                        pass
                    else:
                        self.qCheckBox[int(items[i])].setChecked(True)
                except:
                    pass
        else:
            pass
        self.hidePopup()

    def set_items(self, items):
        self.items = items
        self.loadItems()

    def cancel_select(self):
        for i in range(len(self.qCheckBox)):
            self.qCheckBox[i].setChecked(False)
        self.hidePopup()

    def show(self):
        if len(self.Selectlist()) == 8:
            for i in range(len(self.qCheckBox)):
                if i in self.Selectindex():
                    pass
                else:
                    self.qCheckBox[i].setEnabled(False)
        else:
            for i in range(len(self.qCheckBox)):
                self.qCheckBox[i].setEnabled(True)

    def event(self, event):
        if event.type() == QEvent.Wheel:
            return False
        return super().event(event)

# 自定义输入限制
class AgeValidator(QValidator):
    def __init__(self, max_num):
        super(AgeValidator, self).__init__()
        self.max_num = max_num

    # 传入两个参数： 输入字符串  光标位置
    def validate(self, input_str, pos_int):
        if input_str.isdigit():
            a = int(input_str)
        else:
            return QValidator.Intermediate, input_str, pos_int
        # 判断输入的文本是否在范围之内
        if 1 <= int(input_str) <= self.max_num:
            # 第一个参数是验证通过
            return QValidator.Acceptable, input_str, pos_int
        # elif 1 <= int(input_str) <= 17:
        #     # 第一个参数是中间值 没有判定对错
        #     return QValidator.Intermediate, input_str, pos_int
        else:
            # 判定输入错误
            return QValidator.Invalid, input_str, pos_int


class My_Plot_Widget(PlotWidget):
    def __init__(self, parent=None):
        super(My_Plot_Widget, self).__init__(parent)
        # 创建鼠标是否可用标志
        self.mouse_event_flag = False
        # self.setMenuEnabled(False)

    # def mousePressEvent(self, ev):
    #     """ 重写鼠标点击事件 """
    #     if self.mouse_event_flag:
    #         super().mousePressEvent(ev)
    #     else:
    #         pass

    # def event(self, event):
    #     # print(1, event)
    #     # if event.type() == QEvent.Wheel:
    #     #     print(self.mouse_event_flag)
    #     #     if self.mouse_event_flag:
    #     #         return super().event(event)
    #     #     else:
    #     #         return False
    #     # else:
    #     return super().event(event)

    def wheelEvent(self, event):
        """ 重写滚轮滚动事件 """
        # print(2, event)
        # return False
        if not self.mouse_event_flag:
            event.ignore()
        else:
            return super().wheelEvent(event)

        # event.accept()
        # return super().wheelEvent(event)

    def set_mouse_enable(self, flag):
        self.mouse_event_flag = flag
        # if flag:
        #     self.setMenuEnabled(True)
        # else:
        #     self.setMenuEnabled(False)
